热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

数据项|几个问题_Python入门自学进阶Web框架——14Django的Form验证

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Python入门自学进阶-Web框架——14Django的Form验证相关的知识,希望对你有一定的参考价值。Django

篇首语:本文由编程笔记#小编为大家整理,主要介绍了Python入门自学进阶-Web框架——14Django的Form验证相关的知识,希望对你有一定的参考价值。


Django的Form验证

html>







用户名称:


用户邮箱:


用户邮箱:


% csrf_token %






def logintest(req):
if req.method == "GET":
return render(req,'logintest.html')
elif req.method == "POST":
u = req.POST.get("username")
e = req.POST.get("email")
p = req.POST.get("pwd")
print("对获取的数据进行处理:1,校验;2,数据库操作",u,e,p)
return render(req,'logintest.html',)

存在的几个问题:
1、对用户提交的数据进行验证,要求提示信息准确,即哪个字段的输入不符合要求,在哪个字段进行提示错误信息;
2、如果提交的数据项比较多,后台req.POST.get()会大量出现;
3、如果要进行数据库操作,如使用filter()或create(),参数中要写大量如username=,email=,pwd=。。。等长的参数;
4、对于前端,如果数据项验证失败,即通过form提交了表单,此时前端的所有数据都清空了,而我们期望正确的输入框数据还在(当然,ajax提交不涉及这个问题,ajax提交后数据依然存在);

用户提交数据的验证:

长度、类型、格式验证,重用性要高。

验证分为前端后后端

后端,使用一个模板:
- 邮箱格式
- 用户,名称长度>4
- 密码,长度>7

Django提供了Form验证类模板:

# 定义模板
from django import forms
class LoginForm(forms.Form):
# 模板中的元素
username = forms.CharField(min_length=4)
email = forms.EmailField()

使用验证类进行验证:

def logintest(req):
if req.method == "GET":
return render(req,'logintest.html')
elif req.method == "POST":
obj = LoginForm(req.POST)
# 验证
status = obj.is_valid()
value_right = obj.clean()
print('value_right:',value_right)
value_error = obj.errors
print('value_error:',value_error)
print('status:',status)
if obj.is_valid():
value_right = obj.clean()
# create(**value_right) 数据库增加记录,参数直接使用**value_right
else:
value_error = obj.errors.as_json()
print('value_error_asjson:',value_error)
return render(req,'logintest.html',)

先定义一个模板,这个模板要继承自django的forms中的Form类,然后定义元素,注意,这里的变量名,如username、email不是随意取的,必须与前台form表单中各提交数据标签的name值一致,然后就是具有特定验证功能的CharField()、EmailField()等。在视图函数中使用这个模板
进行验证,先实例化一个模板对象,将req.POST作为参数,这样就会自动获取POST中的对应值进行验证。生成对象并不能验证,还需要调用is_valid()方法,这时才会进行验证,结果为True或False,验证无措,才会返回True,只要有一个字段验证错误,就是False。clean()方法是获取验证正确的字段的一个字典,errors则是错误字段及错误信息的一个无序列表字符串,使用as_json()转换为json字符串。

 因为email字段输入的不符合emailed格式,验证错误,value_error,即errors显示email的错误列表信息,转换为json字符串显示格式,is_valid()结果为false。clean()只是正确字段的字典。

这里有一个问题,就是如果模板中没有定义的字段,在clean()中不能获取,如这里的pwd字段,还需要使用POST.get()获取。

通过错误信息的json格式,可以看到错误的种类,即code的值,这里有invalid——格式不符合,min_length——最小长度不够,required——字段需要值,即字段为空了等。相应的message就是对应错误代码的说明信息,可以是汉字说明。 

# 定义模板
from django import forms
class LoginForm(forms.Form):
# 模板中的元素
username = forms.CharField(min_length=4,error_messages="min_length":"用户名长度不能小于4","required":"用户名不能为空")
email = forms.EmailField(error_messages="invalid":"邮箱名格式不符合要求","required":"邮箱不能为空")

运行打印结果:

value_right:
value_error:

  • username
    • 用户名不能为空
  • email
    • 邮箱不能为空

status: False
value_error_asjson: "username": ["message": "\\u7528\\u6237\\u540d\\u4e0d\\u80fd\\u4e3a\\u7a7a", "code": "required"], "email": ["message": "\\u90ae\\u7bb1\\u4e0d\\u80fd\\u4e3a\\u7a7a", "code": "required"]

转换为json时,汉字转换为Unicode编码了。

 对于errors属性,通过打印结果看,好像是一个字符串,实际是什么呢?通过type(obj.errors),打印出类型:,是一个错误字典,看一下这个类的源代码:

@html_safe
class ErrorDict(dict):
"""
A collection of errors that knows how to display itself in various formats.
The dictionary keys are the field names, and the values are the errors.
"""
def as_data(self):
return f: e.as_data() for f, e in self.items()
def get_json_data(self, escape_html=False):
return f: e.get_json_data(escape_html) for f, e in self.items()
def as_json(self, escape_html=False):
return json.dumps(self.get_json_data(escape_html))
def as_ul(self):
if not self:
return ''
return format_html(
'

    ',
    format_html_join('', '
  • ', self.items())
    )
    def as_text(self):
    output = []
    for field, errors in self.items():
    output.append('* %s' % field)
    output.append('\\n'.join(' * %s' % e for e in errors))
    return '\\n'.join(output)
    def __str__(self):
    return self.as_ul()

    继承自字典dict,我们看到了as_json(),返回的是json.dumps(),即转换为json格式字符串。而其__str__()是返回as_ul(),看as_ul(),其格式就是我们看到的打印的结果。

    因为errors是一个,使用obj.errors['email']访问一下,即
    print(obj.errors['email'])结果为:

    • 邮箱不能为空
    ,这是不是一个字符串呢?打印类型print(type(obj.errors['email'])),结果为:,是一个列表,可以通过下标获取:print('value_error:',value_error['email'][0]),结果:value_error: 邮箱不能为空。

    也就是说,在生成obj对象时,相关的错误信息就存在对象中了,可以将此对象传递给前端:

    def logintest(req):
    if req.method == "GET":
    return render(req,'logintest.html')
    elif req.method == "POST":
    obj = LoginForm(req.POST)
    # 验证
    status = obj.is_valid()
    value_right = obj.clean()
    print('value_right:',value_right)
    value_error = obj.errors
    print('value_error:',value_error['email'][0])
    print('status:',status)
    if obj.is_valid():
    value_right = obj.clean()
    # create(**value_right) 数据库增加记录,参数直接使用**value_right
    else:
    value_error = obj.errors.as_json()
    print('value_error_asjson:',value_error)
    return render(req,'logintest.html','oo':obj)


    用户名称: oo.errors.username.0


    用户邮箱: oo.errors.email.0


    用户邮箱:

    前端只需显示一个错误信息,所以只取索引0的值。对于第一个get请求,没有传递oo对象,对于django来说,没有的对象,返回的就是null,但对于其他语言,有可能出错。

    现在的还有个问题是,form提交后,如果有字段出错,希望字段还保留输入的信息,要实现这个功能,就不能我们自己写input标签,需要Form来实现。

    obj = LoginForm()
    print(obj['username'])
    print(obj['email'])

    结果为:

    对于不传参数的对象,obj['username']是生成一个input标签。

    传递一个参数:obj=LoginForm('username':'qwert','email':'qw@123),则结果为


    在前端,可以使用这种方式自动生成input标签:









    用户名称: oo.username oo.errors.username.0


    用户邮箱: oo.email oo.errors.email.0


    用户邮箱:


    % csrf_token %






    def logintest(req):
    if req.method == "GET":
    obj = LoginForm()
    return render(req,'logintest.html','oo':obj)
    elif req.method == "POST":
    obj = LoginForm(req.POST)
    if obj.is_valid():
    value_right = obj.clean()
    # create(**value_right) 数据库增加记录,参数直接使用**value_right
    else:
    return render(req,'logintest.html','oo':obj)

    这样就能在输入错误后保留原数据。

     需要先运行is_valid()然后才能clean()

    ajax实现提交验证,保留原输入值无需实现,ajax本身不刷新页面,输入值一直保持










    用户名称:


    用户邮箱:


    用户密码:


    % csrf_token %






    前端:获取表单的数据,可以使用serialize()函数,这个获取到的数据可以直接作为ajax的data值使用。

    def loginajax(req):
    if req.method == "GET":
    return render(req,'loginajax.html')
    elif req.method == "POST":
    ret = 'status':True,'error':None,'data':None
    obj = LoginForm(req.POST)
    if obj.is_valid():
    print(obj.clean())
    print(req.POST.get('pwd'))
    else:
    res_str = obj.errors.as_json()
    ret['status'] = False
    ret['error'] = res_str
    return HttpResponse(json.dumps(ret))

    后端ajax提交需要直接HttpResponse返回一个json格式的字符串,使用了dumps()方法。

    上面的实现方式,对于前端,在错误信息处理上,进行了两次JSON.parse(),有些繁琐。

    对后端返回的错误信息进行处理:

    def loginajax(req):
    if req.method == "GET":
    return render(req,'loginajax.html')
    elif req.method == "POST":
    ret = 'status':True,'error':None,'data':None
    obj = LoginForm(req.POST)
    if obj.is_valid():
    print(obj.clean())
    print(req.POST.get('pwd'))
    else:
    # res_str = obj.errors.as_json()
    # ret['status'] = False
    # ret['error'] = res_str
    ret['status'] = False
    ret['error'] = obj.errors.as_data()
    # obj.errors.as_data()的值为:'username': [ValidationError(['用户名不能为空'])], 'email': [ValidationError(['邮箱名格式不符合要求'])]
    # 其value中是如下类的实例:django.core.exceptions.ValidationError
    # 将其进行一次反序列化,即将ValidationError(['用户名不能为空'])进行一次反序列化
    # 最后将ret反序列化,这样一共进行了两次反序列化
    # ValidationError(['用户名不能为空'])进行一次反序列化,因为其在ret中,所以可以在反序列化ret时,使用cls=参数,指定一个进行反序列化的类
    return HttpResponse(json.dumps(ret,cls=JsonCustomEncode))
    from django.core.validators import ValidationError
    class JsonCustomEncode(json.JSONEncoder):
    def default(self, field):
    if isinstance(field,ValidationError):
    return 'code':field.code,'message':field.message
    else:
    return json.JSONEncoder.default(self,field)

    前端










    用户名称:


    用户邮箱:


    用户密码:


    % csrf_token %






    以上是Form验证的基本用法,日常开发中需要的其他一些问题:

    - 除了字符验证和邮件验证,还有哪些验证,可不可以自己定制规则
    - 除了生成input标签,是否可以生成其他标签
    - 显示默认值



    推荐阅读
    • 在Django中提交表单时遇到值错误问题如何解决?
      在Django项目中,当用户提交包含多个选择目标的表单时,可能会遇到值错误问题。本文将探讨如何通过优化表单处理逻辑和验证机制来有效解决这一问题,确保表单数据的准确性和完整性。 ... [详细]
    • DRF框架中Serializer反序列化验证机制详解:深入探讨Validators的应用与优化
      在DRF框架的反序列化验证机制中,除了基本的字段类型和长度校验外,还常常需要进行更为复杂的条件限制校验。通过引入`validators`模块,可以实现自定义校验逻辑,如唯一字段校验等。本文将详细探讨`validators`的使用方法及其优化策略,帮助开发者更好地理解和应用这一重要功能。 ... [详细]
    • SQLite是一种轻量级的关系型数据库管理系统,尽管体积小巧,却能支持高达2TB的数据库容量,每个数据库以单个文件形式存储。本文将详细介绍SQLite在Android开发中的应用,包括其数据存储机制、事务处理方式及数据类型的动态特性。 ... [详细]
    • 本文介绍了如何在Spring框架中配置和使用定时任务,包括初始化配置和动态启动定时器的方法。通过示例代码展示了如何利用Spring的TaskScheduler接口来创建和管理定时任务。 ... [详细]
    • 在Ubuntu系统中配置Python环境变量是确保项目顺利运行的关键步骤。本文介绍了如何将Windows上的Django项目迁移到Ubuntu,并解决因虚拟环境导致的模块缺失问题。通过详细的操作指南,帮助读者正确配置虚拟环境,确保所有第三方库都能被正确识别和使用。此外,还提供了一些实用的技巧,如如何检查环境变量配置是否正确,以及如何在多个虚拟环境之间切换。 ... [详细]
    • 深入解析 Django 中用户模型的自定义方法与技巧 ... [详细]
    • VS Code 中 .vscode 文件夹配置详解
      本文介绍了 VS Code 中 .vscode 文件夹下的配置文件及其作用,包括常用的预定义变量和三个关键配置文件:launch.json、tasks.json 和 c_cpp_properties.json。 ... [详细]
    • 本文探讨了在当前开发环境中使用Django 1.5和Python 3.3的情况下,如何解决AWS和GAE仅支持Python 2.7的问题,并提供了相应的解决方案。 ... [详细]
    • MVC框架下使用DataGrid实现时间筛选与枚举填充
      本文介绍如何在ASP.NET MVC项目中利用DataGrid组件增强搜索功能,具体包括使用jQuery UI的DatePicker插件添加时间筛选条件,并通过枚举数据填充下拉列表。 ... [详细]
    • 本文档提供了详细的MySQL安装步骤,包括解压安装文件、选择安装类型、配置MySQL服务以及设置管理员密码等关键环节,帮助用户顺利完成MySQL的安装。 ... [详细]
    • 作为一名CSS初学者,我在博客园中尝试通过CSS美化页面,特别是为超链接添加图标,以提升阅读体验。本文将分享如何使用CSS和字体图标库来实现这一功能。 ... [详细]
    • 本文探讨了Web API 2中特性的路由机制,特别是如何利用它来构建RESTful风格的URI。文章不仅介绍了基本的特性路由使用方法,还详细说明了如何通过特性路由进行API版本控制、HTTP方法的指定、路由前缀的应用以及路由约束的设置。 ... [详细]
    • 本文探讨了 Boost 库中的 Program Options 组件,这是一个强大的工具,用于解析命令行参数和配置文件。文章介绍了如何正确设置和使用该组件,包括处理复杂选项和负数值的方法。 ... [详细]
    • 本文深入解析了Django框架中的MVT(Model-View-Template)设计模式,详细阐述了其工作原理和应用流程。通过分析URL模式、视图、模型和模板等关键组件,读者将全面理解Django应用程序的架构体系,掌握如何高效地构建和管理Web应用。 ... [详细]
    • 在生产环境中进行高效部署与优化 ... [详细]
    author-avatar
    秋凉凉_e1998
    这个家伙很懒,什么也没留下!
    PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有